/*--------------------------------------------------------------
 * File: devMD8.c 编码类型：C语言  UTF-8
 * Author WRS (1352509846@qq.com)
 * 功能: 模拟的设备2(MD8)功能
 * Version 0.1
 * Date 2024-10-15 
 * 
 * @copyright Copyright (c) 2024
 * 
----------------------------------------------------------------*/
#include "devMD8.h"
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_log.h"
#include "data.h"
#include "ui.h"
#include "Dev_task.h"

extern lv_indev_t * indev_keypad;
extern lv_group_t * group_MD8;
extern const Env_ST Env_st;

// static const char *TAG = "devMD8 ";
char devMD8_Name[20] = {"MD8:   0"};
md8_t md8_info = {0};

TaskHandle_t devMD8_task_Handle = NULL;

/*--------------------------------------------------------------
 * 功能: 初始化md8_info
 * 
----------------------------------------------------------------*/
void md8_info_Init(void)
{
    NVS_data_read_blob(DEV_INFO_NAMESPACE, MD8_key, (uint8_t *)&md8_info, sizeof(md8_t));
    if(md8_info.dev_flag == Info_Save)
    {
        md8_info.devType = emTypeMD8;
        md8_info.dev_index = 0;
        md8_info.dev_SCRindex = 0;
        md8_info.devAddrNow = 0x00;
        // 清零 dev_DI 数组
        memset(md8_info.dev_DI, 0, sizeof(md8_info.dev_DI));
        // 清零 dev_DO 数组
        memset(md8_info.dev_DO, 0, sizeof(md8_info.dev_DO));
        return ;
    }
    md8_info.devType = emTypeMD8;
    md8_info.devLEDtime = emFlashRequest;
    md8_info.dev_num = 1;
    md8_info.dev_index = 0;
    md8_info.dev_SCRindex = 0;
    md8_info.devAddrNow = 0x00;
    md8_info.dev_state = devStart;
}

/*--------------------------------------------------------------
 * 功能: 模拟的设备1初始化
 * 
----------------------------------------------------------------*/
static esp_err_t devMD8_init(void)
{
    ui_Scr5_MD8_screen_init();
    _ui_screen_change(&ui_Scr5_MD8, LV_SCR_LOAD_ANIM_FADE_ON, 100, 0, NULL);
    lv_indev_set_group(indev_keypad, group_MD8);
    lv_group_focus_obj(ui_MD8_DpDown1);   // 默认聚焦到下拉框上
    
    return ESP_OK;
}


/*--------------------------------------------------------------
 * 功能: 模拟设备1启动
 * 
----------------------------------------------------------------*/
void devMD8_Start(void)
{
    devMD8_init();
}

/*--------------------------------------------------------------
 * 功能: 模拟设备2停止
 * 
----------------------------------------------------------------*/
void devMD8_Stop(void)
{
    if(ui_Del_Scr_timer != NULL)
    {
        lv_timer_del(ui_Del_Scr_timer);
        ui_Del_Scr_timer = NULL;
    }
    if(Led_timer != NULL)
    {
        lv_timer_del(Led_timer);
        G_LED_SET(LED_OFF);
        Led_timer = NULL;
    }
    if(ui_Scr5_MD8_timer != NULL)
    {
        lv_timer_del(ui_Scr5_MD8_timer);
        ui_Scr5_MD8_timer = NULL;
    }
    if(ui_Scr5_MD8 != NULL)
    {
        lv_obj_del(ui_Scr5_MD8);
        ui_Scr5_MD8 = NULL;
    }    
}

static void Change_Relay_MD8(uint8_t devIndex, uint8_t DOch, uint8_t val)
{
    uint8_t ch = DOch - MD8_DO_CH0; // DOx
    if(devIndex > MD8_MAX_NUM)
    {
        MY_ERROR("MD8 dev Index ERROR: %d", devIndex);
    }
    if(ch >= MD8_DOChannel)
    {
        MY_ERROR("MD8 DOch ERROR: %d", ch);
    }

    if(val == 1)
    {
        md8_info.dev_DO[devIndex][ch] = val;
    }
    else if(val == 0)   // 关闭
    {
        md8_info.dev_DO[devIndex][ch] = val;
    }
}

/****************************************************************
 **描  述: 写入AO  DO信息
*****************************************************************/
void VARTable_RecVar_MD8(uint32_t ctrl, uint8_t *pValue, void *pVarDes)
{
    struct RS485_VarCtrl_ST *pRS485_VarCtrl_st = (struct RS485_VarCtrl_ST *)&ctrl;
    struct LocalVarDescription_ST *pLocalVarDescription_st = (struct LocalVarDescription_ST *)pVarDes;
    struct RS485_VarName_ST *pRS485_VarName_st = (struct RS485_VarName_ST *)&pLocalVarDescription_st->var_name;
    uint32_t u32_data;
    BitAction BitVal;
    int i;
    uint16_t PartMask;
    uint16_t PartData;
    printf("VarName=%X,%X,%X,COM=%d\n", pRS485_VarName_st->VarName, pLocalVarDescription_st->var_length, pLocalVarDescription_st->VType_un.VarType, pRS485_VarCtrl_st->COMx);
    
    // 485协议
    if (Env_st.COMSet_st[pRS485_VarCtrl_st->COMx].protocol == em485)
    {        
        // 写
        if (pRS485_VarCtrl_st->RWctrl == emRS485Write)
        {
            MY_DEBUG("MD8 Write 0x%02X", pRS485_VarName_st->VarName);
            u32_data = *(uint32_t *)pValue;
            BitVal = u32_data;

            if (pRS485_VarName_st->VarName >= MD8_DO_CH0 && pRS485_VarName_st->VarName < MD8_DO_END)
            {
                MY_DEBUG("DO=%X\n", BitVal);
                Change_Relay_MD8(md8_info.dev_Addrindex, pRS485_VarName_st->VarName, BitVal);
            }
            else if (pRS485_VarName_st->VarName == emVarDOAll)
            {
                PartMask = u32_data >> 16;
                PartData = u32_data & 0xFFFF;
                for (i = 0; i < MD8_DOChannel; i++)
                {
                    BitVal = (PartData >> i) & 1;
                    if (((PartMask >> i) & 1) == 1)
                    {
                        Change_Relay_MD8(md8_info.dev_Addrindex, MD8_DO_CH0 + i, BitVal);
                    }
                }
            }
        }
    }
}

uint32_t VARTable_RecVarR_MD8(uint32_t ctrl, uint8_t *pValue, void *pVarDes, uint8_t *devaddr)
{
    struct RS485_VarCtrl_ST *pRS485_VarCtrl_st = (struct RS485_VarCtrl_ST *)&ctrl;
    struct LocalVarDescription_ST *pLocalVarDescription_st = (struct LocalVarDescription_ST *)pVarDes;
    struct RS485_VarName_ST *pRS485_VarName_st = (struct RS485_VarName_ST *)&pLocalVarDescription_st->var_name;
    uint32_t u32_data = 0;
    // uint8_t VarData[128];
    uint16_t PartData;
    int i;

    printf("VarName=%X,%X,%X,COM=%d\n", pRS485_VarName_st->VarName, pLocalVarDescription_st->var_length, pLocalVarDescription_st->VType_un.VarType, pRS485_VarCtrl_st->COMx);

    if (Env_st.COMSet_st[pRS485_VarCtrl_st->COMx].protocol != em485)
        return 0;
    
    *devaddr = md8_info.devAddr[md8_info.dev_Addrindex];

    // 485协议
    if (pRS485_VarName_st->VarName >= MD8_DI_CH0 && pRS485_VarName_st->VarName < MD8_DI_END)
    {
        MY_DEBUG("read DI %X ", pRS485_VarName_st->VarName);
        u32_data = md8_info.dev_DI[md8_info.dev_Addrindex][pRS485_VarName_st->VarName - MD8_DI_CH0];
        memcpy(pValue, &u32_data, 4);
        return 4;
    }
    else if (pRS485_VarName_st->VarName == emVarDIAll)
    {
        PartData = 0;
        u32_data = 0;
        for (i = 0; i < MD8_DIChannel; i++)
        {
            PartData = md8_info.dev_DI[md8_info.dev_Addrindex][i];
            u32_data |= PartData << i;
            u32_data |= 1 << (i + 16);
        }
        memcpy(pValue, &u32_data, 4);
        return 4;
    }
    else if (pRS485_VarName_st->VarName >= MD8_DO_CH0 && pRS485_VarName_st->VarName < MD8_DO_END)
    {
        // 读取单路DO
        // 读取DO设定值，并不一定是真实值
        u32_data = md8_info.dev_DO[md8_info.dev_Addrindex][pRS485_VarName_st->VarName - MD8_DO_CH0];
        memcpy(&pValue, &u32_data, 4);
        return 4;
    }
    else if (pRS485_VarName_st->VarName == emVarDOAll)
    {
        // 读取所有DO，0x20
        for (i = 0; i < MD8_DOChannel; i++)
        {
            u32_data |= md8_info.dev_DO[md8_info.dev_Addrindex][i] << i;
            u32_data |= 1 << (i + 16);
        }
        memcpy(pValue, &u32_data, 4);
        return 4;
    }
    return 0;
}







